// useCombobox.js
import {ref, computed, onMounted, watch} from 'vue';

export function useCombobox(props, emit) {
    const inputRef = ref(null);
    const isOpen = ref(false);
    const selectedIndex = ref(-1);
    const searchValue = ref('');

    const filteredOptions = computed(() => {
        if (!searchValue.value) return props.options;

        return props.options.filter(option => {
            const label = option[props.labelKey].toLowerCase();
            return label.includes(searchValue.value.toLowerCase());
        });
    });

    const displayValue = computed(() => {
        if (!props.modelValue) return '';

        const selected = props.options.find(option =>
            option[props.valueKey] === props.modelValue
        );

        return selected ? selected[props.labelKey] : props.modelValue;
    });

    function toggleDropdown() {
        isOpen.value = !isOpen.value;
    }

    function openDropdown() {
        isOpen.value = true;
    }

    function closeDropdown() {
        isOpen.value = false;
        selectedIndex.value = -1;
    }

    function handleInput(event) {
        searchValue.value = event.target.value;
        openDropdown();
    }

    function selectOption(option) {
        emit('update:modelValue', option[props.valueKey]);
        searchValue.value = '';
        closeDropdown();
    }

    function handleKeyDown(event) {
        if (!isOpen.value) return;

        switch (event.key) {
            case 'ArrowDown':
                event.preventDefault();
                if (selectedIndex.value < filteredOptions.value.length - 1) {
                    selectedIndex.value++;
                } else {
                    selectedIndex.value = 0;
                }
                scrollToSelected();
                break;

            case 'ArrowUp':
                event.preventDefault();
                if (selectedIndex.value > 0) {
                    selectedIndex.value--;
                } else {
                    selectedIndex.value = filteredOptions.value.length - 1;
                }
                scrollToSelected();
                break;

            case 'Enter':
                if (selectedIndex.value >= 0 && filteredOptions.value[selectedIndex.value]) {
                    selectOption(filteredOptions.value[selectedIndex.value]);
                } else if (filteredOptions.value.length > 0) {
                    selectOption(filteredOptions.value[0]);
                }
                event.preventDefault();
                break;

            case 'Escape':
                closeDropdown();
                event.preventDefault();
                break;
        }
    }

    function scrollToSelected() {
        const menu = inputRef.value?.nextElementSibling;
        if (!menu) return;

        const selectedItem = menu.querySelector('.selected');

        if (selectedItem) {
            selectedItem.scrollIntoView({
                behavior: 'smooth',
                block: 'nearest'
            });
        }
    }

    function clearSearch() {
        searchValue.value = '';
    }

    onMounted(() => {
        document.addEventListener('click', (e) => {
            if (!e.target.closest('.combobox')) {
                closeDropdown();
            }
        });
    });

    watch(() => props.modelValue, (newVal) => {
        searchValue.value = '';
    });

    return {
        inputRef,
        isOpen,
        selectedIndex,
        searchValue,
        filteredOptions,
        displayValue,
        toggleDropdown,
        openDropdown,
        closeDropdown,
        handleInput,
        selectOption,
        handleKeyDown,
        scrollToSelected,
        clearSearch
    };
}